import fsPromises from 'fs/promises';
import SSHClient from './SSHClient.js'
import SSHClientCommander from './SSHClientCommander.js';
class Server {
    /** */
    constructor ( id, options ) {
        this.id = id;
        this.name = options.name;
        this.host = options.host;
        this.port = options.port;
        this.username = options.username;
        this.password = options.password;
        this.icon = options.icon;
        this.sshClient = null;

        this.sftp = null;
    }

    /**
     * 获取当前服务器配置路径
     * @note 即将删除
     */
    getPath ( path ) {
        return `./data/${this.id}/${path}`;
    }

    // 获取本地路径
    localGetPath( path ) {
        return `./data/${this.id}/${path}`;
    }

    /**
     * 获取配置信息
     * @param {*} name 
     */
    async getConfiguration( name ) {
        let path = `./data/${this.id}/${name}.json`;
        try {
            await fsPromises.access(path, fsPromises.F_OK);
        } catch {
            return null;
        }
        
        let content = await fsPromises.readFile(path,{encoding:'utf8'});
        content = JSON.parse(content);
        return content;
    }

    /**
     * 写入配置文件
     * @param {*} name 
     * @param {*} value 
     */
    async setConfiguration( name, value ) {
        let path = `./data/${this.id}/${name}.json`;
        let content = JSON.stringify(value, null, 2);
        await fsPromises.writeFile(path, content);
    }

    /**
     * 获取 SFTP 连接
     * @private
     * @link https://github.com/mscdex/ssh2/blob/master/SFTP.md
     */
    loadSftp() {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            if ( null != $this.sftp ) {
                resolve($this.sftp);
            }

            $this.sshClient.client.sftp((err, sftp) => {
                if (err) {
                    reject(err);
                }
                $this.sftp = sftp;
                resolve(sftp);
            });
        });
    }

    /** 获取 sftp 客户端 */
    getSftp() {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                resolve($this.sftp);
            });
        });
    }

    /** 获取 shell */
    getShell() {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.sshClient.client.shell(( err, stream ) => {
                if (err) {
                    reject(err);
                }
                resolve(stream);
            });
        });
    }

    /** 执行 */
    exec4Stream( cmd ) {
        console.log(`[SSHClient::exec4Stream] ${cmd}`);
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.sshClient.client.exec(cmd, {pty:true}, (error, stream) => {
                if (undefined != error) {
                    reject(error);
                } else {
                    resolve(stream);
                }
            });
        });
    }

    /** 执行命令 */
    exec( cmd ) {
        console.log(`[SSHClient::exec] ${cmd}`);
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.sshClient.client.exec(cmd, {pty:true}, (error, stream) => {
                if (undefined != error) {
                    reject(error);
                }

                let stdout = '';
                let stderr = '';
                stream.on('close', (code, signal) => {
                    console.log(`[SSHClient::exec(${cmd})]\n${stdout}`);
                    resolve(stdout);
                });
                stream.on('data', (data) => { stdout += data; });
                stream.stderr.on('data', (data) => { stderr += data; });
            });
        });
    }

    /**
     * 读取文件内容
     * @param {*} path 
     */
    fileGetContent ( path ) {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                let stream = $this.sftp.createReadStream(path);
                let content = [];
                stream.on('data',function (chunk) {
                    content.push(chunk);
                })
                stream.on('end',function (chunk) {
                    resolve(Buffer.concat(content).toString());
                })
                stream.on('error',function (err) {
                    reject(err);
                })
            });
        });
    }

    /**
     * 写入文件内容
     * @param {*} path 
     * @param {*} content 
     */
    filePutContent( path, content ) {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                let writer = $this.sftp.createWriteStream(path);
                writer.write(content);
                writer.end(() => {
                    resolve();
                });
            });
        });
    }

    /**
     * 删除文件
     * @param {*} path 
     */
    fileRemove( path ) {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                $this.sftp.unlink(path, ( error ) => {
                    if ( undefined == error ) {
                        resolve();
                    } else {
                        reject(error);
                    }
                });
            });
        });
    }

    /**
     * 文件重命名
     * @param {*} oldname 
     * @param {*} newname 
     */
    fileRename( oldname, newname ) {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                $this.sftp.rename(oldname, newname, ( error ) => {
                    if ( undefined == error ) {
                        resolve();
                    } else {
                        reject(error);
                    }
                });
            });
        });
    }

    /**
     * 目录读取
     * @param {*} path 
     */
    dirScan( path ) {
        let $this = this;
        return new Promise(( resolve, reject ) => {
            $this.loadSftp().then(() => {
                $this.sftp.readdir(path, (err, list) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(list);
                    }
                });
            });
        });
    }

    /**
     * 删除目录
     * @param {*} path 
     */
    async dirRemove( path ) {
        let $this = this;
        let deleteDirHandler = function( dir ) {
            return new Promise(( resolve, reject ) => {
                $this.loadSftp().then(() => {
                    $this.sftp.rmdir(path, ( error ) => {
                        if ( undefined == error ) {
                            resolve();
                        } else {
                            reject(error);
                        }
                    });
                });
            });
        };
        
        let files = await this.dirScan(path);
        for ( let i=0; i<files.length; i++ ) {
            let subfile = `${path}/${files[i].filename}`;
            try {
                if ( files[i].attrs.isDirectory() ) {
                    await this.dirRemove(subfile);
                } else {
                    await this.fileRemove(subfile);
                }
            } catch ( error ) {
                throw error;
            } 
        }

        await deleteDirHandler(path);
    }

    /** 获取 SSH 客户端 */
    getSshClient() {
        if ( null != this.sshClient ) {
            return this.sshClient;
        }

        let client = new SSHClient(this);
        this.sshClient = client;
        return this.sshClient;
    }
    
    
    
    /** */
    async getCommander() {
        let client = await this.getSshClient();
        return new SSHClientCommander(client);
    }
}
export default Server;